//==============================================================================
// Sequence.hh
// ----------------------------------------------------------------------------
// Classes that represent sequences and the information associated with 
// them (quality, traces, etc.).  Also includes Sequence and other vectors
// as convenience classes. 
//
//------------------------------------------------------------------------------
// $Id: Sequence.hh,v 1.1 2000/02/01 22:16:31 kdurbin Exp kdurbin $
//------------------------------------------------------------------------------
// $Log: Sequence.hh,v $
// Revision 1.1  2000/02/01 22:16:31  kdurbin
// Initial revision
//
//
//==============================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8
//

#include "LocalSTL.hh"
#include "ParseUtils.hh"

#ifndef _SEQUENCE
#define _SEQUENCE


// It's clear to me that I'd like to abstract Sequence so that I can drop in 
// either this implementation, the Sequence3Bit implementation, or possibly 
// some other implementation.  Trouble is I already have a lot of code that 
// uses this class.  
// 
// Since Sequence and Sequence3Bit have different relationships to their
// underlying vectors, I will either need to override such vector<> functions
// as size(), resize(), and so on, or replace them with other functions. 
// In the latter case I will need to find and replace all instances in 
// my existing code.  A big job. 
// 
// 

/* 
class BasicSequence {
 public:
  char BaseAt(int idx) = 0;
  int  size() = 0;
  void resize() = 0;
};

class Sequence3Bit : BasicSequence{

};

class Sequence : BasicSequence{

};

class FastSequence : BasicSequence {
  
};
*/


//------------------------------------------------------------------------------
// * Sequence
//------------------------------------------------------------------------------
// A sequence.  
//
class Sequence: public vector<char> {
 public:

  vector<int> mDepadded2Padded;
  vector<int> mPadded2Depadded;

  // Operator () is now the preferred way to get a base 
  // from a Sequence.  This is to preserve compatibility between 
  // the Sequence class and the Sequence3Bit class. 
  inline unsigned char operator()(size_type n){
    return((*this)[n]);
  }

  // Provided for compatibility with Sequence3Bit. 
  int bases(){
    return(size());
  }


  //~Sequence(){};
  Sequence(){
  };

  Sequence(const char*pSeqStr){
    (*this).InitFromCString(pSeqStr);
  }

  Sequence(Sequence &S, int start, int end){
    S.GetSubSequence((*this),start,end);
  }

  // Make sure you can print out a sequence just like you can a string.
  friend ostream& operator<<(ostream& os,const Sequence &s){
    for(int i = 0;i<s.size();i++){
      os<<s[i];
    }
    return(os);
  }

  void ComputePadded2Depadded();
  void ComputeDepadded2Padded();

  int  Depadded2Padded(int DepaddedCIdx);
  int  Padded2Depadded(int PaddedCIdx);

  //  int  D2P(int DepaddedCIdx);
  //int  P2D(int PaddedCIdx);

  void ReverseComplement();
  bool IsBase(char a);
  bool IsBaseNX(char base);

  void Reverse();
  void Complement();
  void Nify();
  
  // Sequence validating functions. 
  bool ContainsOnlyBasesSafe();
  bool ContainsOnlyBasesSafe(int start,int chklen);
  bool ContainsNonBaseSafe(int start,int chklen);								 

  // Fast limited check. 
  bool OnlyUpperCaseBases();
  bool OnlyUpperCaseBases(int start,int cklen);



  void Print(ostream &os);
  void Print(){Print(cout);};
  void PrintSeq(ostream &os);
  void PrintSeq(){PrintSeq(cout);};

  long  Find(Sequence &target);
  long  Find(Sequence::iterator iStart,Sequence::iterator iEnd);
  long  FindEndOf(Sequence TargetSeq, bool &bIsReversed);
  void FindEndOfTag(Sequence &TargetSeq,int TagStart,int TagEnd,
		    long &Location,bool &bIsReversed);

  void Concatenate(Sequence &seq);
  void ConcatenateCString(char *cstring);
  void ConcatenateString(string &s);

  void ConcatenateNonWhiteSpace(string &s);

  void ConcatenateStringSafe(string &s);

  // KJD I have two versions.  What is the right way?
  void InitFromCString(char *cstring);
  void InitFromCString(const char *cstring);  

  void InitFromString(string &source);
  void CopyToCString(char *cstring);
  void CopyToString(string &stringout);
  void ToLowerCase();
  void ToUpperCase();
  void GetSubSequence(Sequence &seq,long start,long end);

  void ComputeGCStats(int &NumBases, int &NumGC, int &NumCPG);
  
  void Trim(long start,long end);

  Sequence &operator+(Sequence &seq){
    (*this).Concatenate(seq);
    return(*this);
  }

  Sequence& operator+=(char a){
    register int oldSize = size();
    resize(oldSize+1);
    (*this)[oldSize]=a;
    return(*this);
  }

  Sequence& operator+=(Sequence &a){
    (*this).Concatenate(a);
    return(*this);
  }


  Sequence & operator=(const char*pSeqStr){
    (*this).InitFromCString(pSeqStr);
    return(*this);
  }

  // KJD This is quite messy.  Should be cleaned up. 
  string mDescription;  // Used when reading a description in from a file
  string mName;


  char ComplementBase(char base);

 protected:
  

};//-------| End Sequence Class |----------------------------------------------

//------------------------------------------------------------------------------
// * SequenceQuality
//------------------------------------------------------------------------------
// 
class SequenceQuality: public vector<int>{
 public:
  //~SequenceQuality(){};
  //SequenceQuality(){};

  void Reverse();
  void Print();
  void Print(ostream &fout);


  void Concatenate(SequenceQuality &Qual);

  int  CountPhred20();
  long FindPhred20(long start=0);
  long RFindPhred20();
  long RFindPhred20(long start);
  void Trim(long start,long end);

  string mDescription;
  string mName;

 protected:

};


//------------------------------------------------------------------------------
// * SequenceQuality (deprecated)
//------------------------------------------------------------------------------
// 
class SequenceWithQuality : public Sequence{
 public:

  SequenceQuality mQuality;

  void TrimPhred20(){
    long P20Start = mQuality.FindPhred20();
    long P20End = mQuality.RFindPhred20();
	 
    mQuality.Trim(P20Start,P20End);
    (*this).Trim(P20Start,P20End);
  }
};


//------------------------------------------------------------------------------
// * SequenceTrace
//------------------------------------------------------------------------------
// 
class SequenceTrace: public vector<int>{
 public:
  //~SequenceTrace(){};
  //SequenceTrace(){};

 protected:

};

//------------------------------------------------------------------------------
// * SequenceVector
//------------------------------------------------------------------------------
// A vector of sequences.  
//
class SequenceVector: public vector<Sequence>{
 public:

  //~SequenceVector(){};
  //SequenceVector(){};


  int  MaxSize();
  int  N50();

  void GetSortedSizes(vector<int> &sizeList);

  void SizeStats(float &mean,float &variance);
  void GrowVec();
  void AddSequence(Sequence &Seq);
  void AddSubSequence(Sequence &Seq,long start,long end);
  long TotalBases();
  void FindEndOf(Sequence &Query,int &SeqIdx,long &Location,bool &bIsReverse);

  void Print(ostream &os);
  void Print(){Print(cout);};

  string mDescription;
 protected:
};


//------------------------------------------------------------------------------
// * SequenceQualityVector
//------------------------------------------------------------------------------
// A vector of sequence quality.  
//
class SequenceQualityVector: public vector<SequenceQuality>{
 public:

  //~SequenceQualityVector(){};
  //SequenceQualityVector():self(*this){};
  //SequenceQualityVector(){};

  void Phred20Stats(float &mean,float &variance);
  long Phred20Total();

  void GrowVec();
  void AddQuality(SequenceQuality &Qual);

  void Print(ostream &fout);

 protected:
  //SequenceQualityVector &self;
};


//------------------------------------------------------------------------------
// * SequenceTraceVector
//------------------------------------------------------------------------------
// 
class SequenceTraceVector: public vector<SequenceTrace>{
 public:
  ~SequenceTraceVector(){};
  SequenceTraceVector(){};

 protected:

};


#endif


